import mechanize, cookielib
import re
import time
import math
from datetime import datetime
import sys
import getopt
from CalculateUser import calculateUser
from ConfigUser import *
from SaveAndApply import *
from Logger import *
from uuid import uuid1

configObj = None
logger = None

def initBrowser():
    print "Initialize Browser"
    br = mechanize.Browser(factory=mechanize.RobustFactory())
    # Cookie Jar
    cj = cookielib.LWPCookieJar()
    br.set_cookiejar(cj)

    # Browser options
    br.set_handle_equiv(True)
    #br.set_handle_gzip(True)
    br.set_handle_redirect(True)
    br.set_handle_referer(True)
    br.set_handle_robots(False)

    # Follows refresh 0 but not hangs on refresh > 0
    br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

    # Want debugging messages?
    #br.set_debug_http(True)
    #br.set_debug_redirects(True)
    #br.set_debug_responses(True)

    br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]    
    logger.log("LOG", 0, "Browser Initialized")
    return br

def login(br):
#######  Login  #######
    print "Login"
    br.open("https://tools.cleanpowerfinance.com/user/login")
    br.select_form("loginform")
    br["username"] = configObj.getProperty("username")
    br["password"]=configObj.getProperty("password")
    try:
        br.submit()
    except:
        logger.log("ERROR", "1", str(sys.exc_info()[0])+" " +str(sys.exc_info()[1]), sys.exc_traceback.print_stack())
        raise sys.exc_value
    logger.log("LOG",0,"Succesfully Logged in as %s"%configObj.getProperty("username"))
    return br

def gotoScreen(br, screen):
    print "going to "+screen
    #screens = ["summary", "location", "energy", "equip", "analysis", "review","proposal"]
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"] = screen
    br.submit()
    return br


def clickAddJob(br):
    print "clicking Add a New Job"
    br.select_form(nr=0)
    try:
        br.submit()
    except:
        logger.log("ERROR","1",str(sys.exc_info()[0])+" "+str(sys.exc_info()[1]),sys.exc_traceback.print_stack())
        raise sys.exc_value
    logger.log("LOG",0,"Successfully clicked add a new job")
    return br

def addUserSummary(br):
    br.select_form("jobscript")
    br.find_control("nextpage").readonly = False
    br["nextpage"]="location"
    br["ctype"]=[configObj.getProperty("ctype")]
    br["jobref"]=configObj.getProperty("jobref")
    br["cfirstname"]=configObj.getProperty("cfirstname")
    br["clastname"]=configObj.getProperty("clastname")
    br["cphone1"]=configObj.getProperty("cphone1")
    br["cemail"]=configObj.getProperty("cemail")
    br["caddress1"]=configObj.getProperty("caddress1")
    br["ccity"]=configObj.getProperty("ccity")
    br["czip"]=configObj.getProperty("czip")
    br.submit()
    return br

def fillLocation(br, lstTilt, lstAzimuth, lstShading):
#######  Go to the correct screen  #######
    assert len(lstTilt)==len(lstAzimuth) and len(lstShading)==len(lstTilt)
    print "Filling Location Tab"
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"]="energy"
    response = br.submit()
    br.select_form(nr=0)
    if configObj.getProperty("siteassessment")=="1":
        br["siteassessment"] = [configObj.getProperty("siteassessment")]
    br["cutility1"] = [configObj.getProperty("cutility1")]
    br["usetou"] = [configObj.getProperty("usetou")]
    for i in xrange(len(lstTilt)):
        br["cheight"+str(i+1)] = configObj.getProperty("cheight"+str(i+1))
        br["clength"+str(i+1)] = configObj.getProperty("clength"+str(i+1))
        br["inoct"+str(i+1)] = [configObj.getProperty("inoct"+str(i+1))]
        br["tilt"+str(i+1)] = [lstTilt[i]]
        br["azimuth"+str(i+1)] = [lstAzimuth[i]]
        for j in xrange(12):
            br["shade"+str(i+1)+str(j+1)] = lstShading[i][j]
    br["soiling"] = [configObj.getProperty("soiling")]
    br.submit();
    return br

def fillEnergy(br):
    print "Filling Energy Tab"
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"]="equip"
    presolarrate = configObj.getProperty("presolarrate1")
    optionValue = getOptionValue(br.response().read(), presolarrate)
    br["presolarrate1"] = [optionValue]
    br["euse1"] = configObj.getProperty("euse")[0]
    br["euse2"] = configObj.getProperty("euse")[1]
    br["euse3"] = configObj.getProperty("euse")[2]
    br["euse4"] = configObj.getProperty("euse")[3]
    br["euse5"] = configObj.getProperty("euse")[4]
    br["euse6"] = configObj.getProperty("euse")[5]
    br["euse7"] = configObj.getProperty("euse")[6]
    br["euse8"] = configObj.getProperty("euse")[7]
    br["euse9"] = configObj.getProperty("euse")[8]
    br["euse10"] = configObj.getProperty("euse")[9]
    br["euse11"] = configObj.getProperty("euse")[10]
    br["euse12"] = configObj.getProperty("euse")[11]
    br.submit()
    #try:
    #    response = br.submit()
    #except:
    #    print "ERROR: There was an error submitting the energy tab.  The customer has already been created.  You can either start again and create a new customer, or log in and manually complete the current customer."
    #    return None
    return br

def getOptionValue(html, option):
    value = html.split(option)
    if len(value)==1:
        raise IOError("Option Value not found.  Either the Solar panel, Inverter, presolarrate, or crate1 Value was incorrect.")
    value=value[0]
    value = value.split("value=\"")
    value = value[len(value)-1]
    value = value.split("\"")[0]
    return value

def fillEquip(br):
    print "Filling Equip Tab"
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"]="analysis"
    html = br.response().read()
    collectorValue = configObj.getProperty("collectorid")
    optionValue = getOptionValue(html, collectorValue)
    br["collectorid"] = [optionValue]
    inverterid = configObj.getProperty("inverterid")
    optionValue = getOptionValue(html, inverterid)
    br["inverterid"] = [optionValue]
    try:
        postSolar = configObj.getProperty("crate1")    
        optionValue = getOptionValue(html, postSolar)
    except IOError as e:
        postSolar = configObj.getProperty("presolarrate1")
        optionValue = getOptionValue(html, postSolar)
    br["crate1"]=[optionValue]
    br["mrp61739"]= [configObj.getProperty("mrp61739")]
    incentiveStep = configObj.getProperty("incentive")
    if incentiveStep == "9":
        br["incent2616"] = ["1"]
    elif incentiveStep =="10":
        br["incent2617"] = ["1"]
    if configObj.getProperty("incent499")=="1":
        br["incent499"] = ["1"]
    br.submit()
    #try:
    #    br.submit()
    #except:
    #    print "ERROR: There was an error submitting the Equip tab.  The customer has already been created.  You can either start again and create a new customer, or log in and manually complete the current customer."
    #    return None
    return br

def fillAnalysis(br):
    print "Filling Analysis Tab"
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"] = "review"
    panels = configObj.getProperty("nummod")
    if isinstance(panels,str):
        panels = [panels]
    kwh = configObj.getProperty("kwh")
    dsnfactor = configObj.getProperty("dsnfactor")
    for i in xrange(len(panels)):
        br["nummod"+str(i+1)] = panels[i]
        br["kwh"+str(i+1)] = kwh[i]
        br["numinverter"+str(i+1)] = panels[i]
        br["dsnfactor"+str(i+1)] = dsnfactor[i]
    try:
        br.submit()
    except:
        print "ERROR: There was an error submitting the analysis tab.  The customer has already been created.  You can either start again and create a new customer, or log in and manually complete the current customer."
        return None
    return br

def fillReview(br):
    print "Filling Review Tab"
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"] = "review"
    proposal_id = br.response().read().split("proposal_id/")[1]
    proposal_id = proposal_id[0:6]
    
    success = False
    matchedPrice = int(configObj.getProperty("matchedPrice"))
    minGM = 0
    maxGM = 100
    GMbr = initBrowser()
    GMbr = login(GMbr)
    GM=None
    this_year = configObj.getProperty("installthisyear")
    product_id = configObj.getProperty("product")
    kwhs = configObj.getProperty("kwh")
    if isinstance(kwhs, str):
        kwhs=[kwhs]
    power = 0.0
    for kwh in kwhs:
        power = power + float(kwh)
    power = power * 1000
    maxPrice = power * 7.25
    if product_id=="Greenday PPA":
        product_id="31"
        down = configObj.getProperty("initialpayment")
        ann_increase = configObj.getProperty("annualincrease")
        ####    Binary Search for the Finance Payment    
        while not success:
            GM = (minGM+maxGM)/2.0
            data = calculateUser(GMbr,product_id,proposal_id, str(GM), ann_increase, down, this_year)
            sys_price = int(data[1][1:].replace(",",""))
            fin_payment = data[6]
            fin_payment = fin_payment.split(" + ")[0]
            fin_payment = int(fin_payment.split("($")[1])
            if sys_price<maxPrice and fin_payment <= matchedPrice and maxGM-minGM<.001:
                success=True
            elif sys_price>maxPrice:
                maxGM = GM
                #print sys_price, "SP > maxP", maxPrice
            elif fin_payment<=matchedPrice:
                minGM=GM
                #print fin_payment,"FP < MP", matchedPrice
            elif fin_payment>matchedPrice:
                maxGM=GM
                #print fin_payment, "FP > MP", matchedPrice
            #print "SysPrice: ", sys_price
            #print "maxPrice: ",maxPrice
            #print "matchedPrice: ", matchedPrice
            #print "GM: ", GM
            #print "finance Payment: ", fin_payment
        GM = math.floor(GM * 1000)/1000.0
        GMbr = saveAndApply(GMbr, proposal_id, GM, product_id, down, ann_increase, this_year)
    else:
        product_id="32"
        while not success:
            GM = (minGM+maxGM)/2.0
            data = calculateUser(GMbr, product_id,proposal_id,str(GM), "", "",this_year)
            sys_price = int(data[1][1:].replace(",",""))
            initPayment = int(data[3][1:].replace(",",""))
            if sys_price<maxPrice and initPayment<=matchedPrice and maxGM-minGM<.001:
                success=True
            elif sys_price>maxPrice:
                maxGM=GM
            elif initPayment<=matchedPrice:
                minGM=GM
            elif initPayment>matchedPrice:
                maxGM=GM
        GM = math.floor(GM*1000)/1000.0
        GMbr = saveAndApply(GMbr, proposal_id, GM, product_id, "", "", this_year)
        
    br.new_control('hidden','primary1',attrs = dict(name='primary1'))
    br.new_control('hidden','margin1',attrs = dict(name='margin1'))
    br.new_control('hidden','no_cost_overrides',attrs = dict(name='no_cost_overrides'))
    br.set_all_readonly(False)
    br["primary1"]="on"
    br["margin1"]=str(GM)
    br["no_cost_overrides"] = "1"
    try:
        br.submit()
    except:
        print "ERROR: There was an error submitting the review tab.  The customer has already been created.  You can either start again and create a new customer, or log in and manually complete the current customer."
        return None
    return br

def getProposal(br):
    br.select_form(nr=0)
    br.find_control("nextpage").readonly = False
    br["nextpage"] = "proposal"
    br.submit()
    br.select_form(nr=0)
    filename = configObj.getProperty("cfirstname")+"_"+configObj.getProperty("clastname")
    filename = filename + "_"+configObj.getProperty("caddress1")+"_homeowner_packet.pdf"
    filename = str(os.getcwd())+"/CustomerPackets/"+ filename
    d = os.path.dirname("CustomerPackets/")
    if not os.path.exists(d):
        os.makedirs(d)
    linkname=None
    installLinkName=None
    if configObj.getProperty("product")=="Greenday PPA":
        linkname = "forms_to_print=68&user_formset_job="
        installLinkName = "forms_to_print=69&user_formset_job="
    else:
        linkname = "forms_to_print=64&user_formset_job="
        installLinkName = "forms_to_print=65&user_formset_job="
    link = br.links(url_regex=linkname).next()
    (fn, headers) = br.retrieve("https://tools.cleanpowerfinance.com"+link.url,filename)
    print "File saved at :", fn
    installPacketFN = filename[:-20]+"install_packet.pdf"
    link = br.links(url_regex=installLinkName).next()
    (fn, headers) = br.retrieve("https://tools.cleanpowerfinance.com"+link.url,installPacketFN)
    print "File saved at :", fn
##    try:
##        linkname=None
##        if configObj.getProperty("product")=="Greenday PPA":
##            linkname = "68&user_formset_job="
##        else:
##            linkname = "64&user_formset_job="
##        logger.log("LOG", 0, "LINKENAME: "+linkname)
##        link = br.links(url_regex=linkname).next()
##        logger.log("LOG",0,"LINK: "+link)
##        (fn, headers) = br.retrieve("https://tools.cleanpowerfinance.com"+link.url,filename)
##        print "File saved at :", fn
##    except IOError as e:
##        logger.logError(0,str(e)) #Continue this line
##    except:
##        logger.logError(0,str(sys.exc_info()[0])+" " +str(sys.exc_info()[1]),)# sys.exc_traceback.print_stack())
##        print "These settings did not result in a Home Owner Packet. Log in Manually and set the Gross Margin on the Analysis Page."
    return br

def usage():
   print "Usage for CPFToolsSSUser"
   print "To run this file from the command line, navigate to the exe file on the command line.  Then type CPFToolsSSUser.exe."
   print "If you with to specify a config file you can add -c config_file_name or --configfile=config_file_name"
   print "For help type CPFToolsSSUser --help or -h"

def main(argv):
  global logger
  logger = Logger()
  try: 
    opts, args = getopt.getopt(argv, "c:h",["configfile=", "help"])
  except getopt.GetoptError:
    usage()
    sys.exit(2)
  print "Checking inputs"
  thisYear = False
  getOne = False
  configFilePassed = False
  configFile = "configUser.txt"
  for opt, arg in opts:
    if opt in ("-h", "--help"):
      usage()
      sys.exit()
    elif opt in ("-c", "--configFile="):
      configFile = arg
      configFilePassed = True    
    else:
      print "unhandled option"
      usage()
      sys.exit(2)
  global configObj
  try:
      configObj = Config(configFile, logger.guid)
  except IOError as e:
      print e
      x = raw_input("Press Enter to finish!")
      sys.exit(2)
  success = False
  attempts = 1
  failAfter = 3
  while not success:
      if attempts > failAfter:
          print "I have tried 3 times without success. Please Try again Later"
          break
      br = initBrowser()
      try:
        br = login(br)
      except (urllib2.URLError,BadStatusLine):
        print "URLERROR: A Connection could not be established: ",sys.exc_value
        print "We have tried %d times.  I will try %d times." % (attempts, failAfter)
        attempts = attempts + 1
        continue
      br.open("https://tools.cleanpowerfinance.com/secure/dashboard.php")
      br = clickAddJob(br)
      br = addUserSummary(br)
      counter = 1
      tilt = configObj.getProperty("tilt")
      if isinstance(tilt,str):
          tilt = [tilt]
      azimuth = configObj.getProperty("azimuth")
      if isinstance(azimuth,str):
          azimuth = [azimuth]
      lstShading = []
      while True:
          if configObj.hasProperty("shading"+str(counter)):
              lstShading.append(configObj.getProperty("shading"+str(counter)))
          else:
              break
          counter = counter + 1
      br = fillLocation(br, tilt, azimuth, lstShading)
      br = fillEnergy(br)
      br = fillEquip(br)
      br = fillAnalysis(br)
      br = fillReview(br)
      br = getProposal(br)
      success = True
      finish = input("Press Enter when finished!")
      #except:
      #    print "This job did not complete correctly.  Either try again, or log in and enter the information manually."
      #    print sys.exc_info()[1], " ", sys.exc_info()[0]
      #    print sys.exc_info()[2]
      #    sys.exit(2)
          
  #return br
      
if __name__=="__main__":
  br = main(sys.argv[1:])
